/**
 * Copyright (c) 2019 Coder League
 * All rights reserved.
 *
 * File：OrdersService.java
 * History:
 *         2019年6月6日: Initially created, CJH.
 */
package club.coderleague.ilsp.service.orders;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.validation.ValidationException;

import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import club.coderleague.ilsp.cache.CacheManager;
import club.coderleague.ilsp.common.domain.beans.GoodsInfo;
import club.coderleague.ilsp.common.domain.beans.OfflineGoods;
import club.coderleague.ilsp.common.domain.beans.OfflineOrder;
import club.coderleague.ilsp.common.domain.beans.OnlineOrder;
import club.coderleague.ilsp.common.domain.beans.PayOrder;
import club.coderleague.ilsp.common.domain.beans.PaymentInterfaceResponse;
import club.coderleague.ilsp.common.domain.beans.PreferentialResult;
import club.coderleague.ilsp.common.domain.beans.SubitemPreferential;
import club.coderleague.ilsp.common.domain.beans.SystemConfig;
import club.coderleague.ilsp.common.domain.beans.OnlineOrder.OnlineGood;
import club.coderleague.ilsp.common.domain.beans.OnlineOrder.OrderMerchant;
import club.coderleague.ilsp.common.domain.enums.EntityState;
import club.coderleague.ilsp.common.domain.enums.NotifyType;
import club.coderleague.ilsp.common.domain.enums.OrderCancelType;
import club.coderleague.ilsp.common.domain.enums.OrderDeliveryMode;
import club.coderleague.ilsp.common.domain.enums.OrderDeliveryState;
import club.coderleague.ilsp.common.domain.enums.OrderDeliveryTime;
import club.coderleague.ilsp.common.domain.enums.OrderOrigin;
import club.coderleague.ilsp.common.domain.enums.OrderPaymentMode;
import club.coderleague.ilsp.common.domain.enums.OrderPaymentState;
import club.coderleague.ilsp.common.domain.enums.OrderRefundApplyType;
import club.coderleague.ilsp.common.domain.enums.OrderType;
import club.coderleague.ilsp.common.exception.MessageInfoException;
import club.coderleague.ilsp.common.exception.MessageWarnException;
import club.coderleague.ilsp.common.rocketmq.consumer.OrderTimeoutConsumer;
import club.coderleague.ilsp.common.rocketmq.consumer.OrderTimeoutConsumer.OrderTimeoutTagsEnum;
import club.coderleague.ilsp.common.rocketmq.producer.OrderTimeoutProducer;
import club.coderleague.ilsp.dao.GoodPhotosMgrDao;
import club.coderleague.ilsp.dao.GoodSalesDao;
import club.coderleague.ilsp.dao.GoodSpecsDao;
import club.coderleague.ilsp.dao.GoodsMgrDao;
import club.coderleague.ilsp.dao.MembersDao;
import club.coderleague.ilsp.dao.MerchantSettlesDao;
import club.coderleague.ilsp.dao.OrderGoodsDao;
import club.coderleague.ilsp.dao.OrderPresplitsDao;
import club.coderleague.ilsp.dao.OrdersDao;
import club.coderleague.ilsp.dao.ReceivingAddressesDao;
import club.coderleague.ilsp.dao.RefundGoodsDao;
import club.coderleague.ilsp.dao.RefundRecordsDao;
import club.coderleague.ilsp.dao.ShoppingCartsDao;
import club.coderleague.ilsp.entities.Goodphotos;
import club.coderleague.ilsp.entities.Goods;
import club.coderleague.ilsp.entities.Goodsales;
import club.coderleague.ilsp.entities.Goodspecs;
import club.coderleague.ilsp.entities.Merchantsettles;
import club.coderleague.ilsp.entities.Ordergoods;
import club.coderleague.ilsp.entities.Orderpresplits;
import club.coderleague.ilsp.entities.Orders;
import club.coderleague.ilsp.entities.Receivingaddresses;
import club.coderleague.ilsp.entities.Refundgoods;
import club.coderleague.ilsp.entities.Refundrecords;
import club.coderleague.ilsp.entities.Shoppingcarts;
import club.coderleague.ilsp.service.capitalrecords.CapitalRecordsService;
import club.coderleague.ilsp.service.diamondrecords.DiamondRecordsService;
import club.coderleague.ilsp.service.integralrecords.IntegralRecordsService;
import club.coderleague.ilsp.service.interfaces.AbstractInterfaceService;
import club.coderleague.ilsp.service.interfaces.AliyunInterfaceService;

/**
 * 订单Service
 * 
 * @author CJH
 */
@Service
public class OrdersService {
	private static final Logger LOGGER = LoggerFactory.getLogger(OrdersService.class);
	private static final double MIN_PAY_AMOUNT = 1.0;
	
	/**
	 * 订单Dao
	 */
	private @Autowired OrdersDao ordersDao;
	
	/**
	 * 商品销售Dao
	 */
	private @Autowired GoodSalesDao goodSalesDao;
	
	/**
	 * 商品规格Dao
	 */
	private @Autowired GoodSpecsDao goodSpecsDao;
	
	/**
	 * 商品Dao
	 */
	private @Autowired GoodsMgrDao goodsDao;
	
	/**
	 * 商品相册Dao
	 */
	private @Autowired GoodPhotosMgrDao goodPhotosDao;
	
	/**
	 * 订单商品Dao
	 */
	private @Autowired OrderGoodsDao orderGoodsDao;
	
	/**
	 * 会员Dao
	 */
	private @Autowired MembersDao membersDao;
	
	/**
	 * 积分记录Service
	 */
	private @Autowired IntegralRecordsService integralRecordsService;
	
	/**
	 * 钻石记录Service
	 */
	private @Autowired DiamondRecordsService diamondRecordsService;
	
	/**
	 * 资金记录Service
	 */
	private @Autowired CapitalRecordsService capitalRecordsService;
	
	/**
	 * 缓存Manager
	 */
	private @Autowired CacheManager cacheManager;
	
	/**
	 * 收货地址Dao
	 */
	private @Autowired ReceivingAddressesDao receivingAddressesDao;
	
	/**
	 * 商户入驻Dao
	 */
	private @Autowired MerchantSettlesDao merchantSettlesDao;
	
	/**
	 * 订单预拆分Dao
	 */
	private @Autowired OrderPresplitsDao orderPresplitsDao;
	
	/**
	 * 购物车Dao
	 */
	private @Autowired ShoppingCartsDao shoppingCartsDao;
	
	/**
	 * 订单超时消息生产者
	 */
	private @Autowired OrderTimeoutProducer orderTimeoutProducer;
	
	/**
	 * 退款记录Dao
	 */
	private @Autowired RefundRecordsDao refundRecordsDao;
	
	/**
	 * 退款商品Dao
	 */
	private @Autowired RefundGoodsDao refundGoodsDao;
	
	private @Autowired AliyunInterfaceService aliyunInterfaceService;
	
	/**
	 * 新增线下订单
	 * 
	 * @author CJH 2019年7月2日
	 * @param offlineorder 线下订单
	 * @return 订单主键
	 */
	public Long insertOfflineOrder(OfflineOrder offlineorder) {
		// 校验线下订单参数有效性
		List<OfflineGoods> offlinegoods = offlineorder.getOfflinegoods();
		if (offlinegoods == null || offlinegoods.isEmpty()) {
			throw new ValidationException("购物商品不能为空");
		}
		for (OfflineGoods shoppinggood : offlinegoods) {
			if (shoppinggood.getSaleid() == null) {
				throw new ValidationException("销售标识不能为空");
			}
			shoppinggood.setGoodnumber(shoppinggood.getGoodnumber() != null ? shoppinggood.getGoodnumber() : 0);
			if (shoppinggood.getGoodnumber() <= 0) {
				throw new ValidationException("商品数量小于等于0");
			}
		}
		
		// 新增订单
		Orders mainorder = new Orders();
		mainorder.setEntitystate(EntityState.TBD.getValue());
		mainorder.setOrderorigin(OrderOrigin.OFFLINE.getValue());
		mainorder.setOrdertype(OrderType.NORMAL.getValue());
		mainorder.setDeliverycost(0d);
		mainorder.setDeliverystate(OrderDeliveryState.UNSHIPPED.getValue());
		mainorder.setDeliverymode(OrderDeliveryMode.NO_DELIVERY.getValue());
		mainorder.setPaymentstate(OrderPaymentState.UNPAID.getValue());
		mainorder.setOrdertime(new Date());
		
		// 计算商品总额
		BigDecimal goodtotal = new BigDecimal(0);
		List<Ordergoods> ordergoods = new ArrayList<>();
		for (OfflineGoods offlinegood : offlinegoods) {
			Goodsales goodsale = goodSalesDao.getOne(offlinegood.getSaleid());
			if (mainorder.getMarketid() == null) {
				Merchantsettles merchantsettle = merchantSettlesDao.getOne(goodsale.getSettleid());
				mainorder.setMerchantid(merchantsettle.getMerchantid());
				mainorder.setMarketid(merchantsettle.getMarketid());
			}
			BigDecimal goodnumber = new BigDecimal(offlinegood.getGoodnumber().toString());
			BigDecimal goodprice = new BigDecimal(goodsale.getGoodprice().toString());
			BigDecimal onegoodtotal = goodprice.multiply(goodnumber);
			goodtotal = goodtotal.add(onegoodtotal);
			Goodspecs goodspec = goodSpecsDao.getOne(goodsale.getSpecid());
			Goods good = goodsDao.getOne(goodspec.getGoodid());
			Goodphotos goodphotos = goodPhotosDao.getCoverphotoByGoodid(good.getEntityid());
			ordergoods.add(new Ordergoods(EntityState.VALID.getValue(), null, offlinegood.getSaleid(), null, good.getGoodname(), 
					good.getGoodorigin(), goodphotos.getPhotopath(), goodspec.getSpecdefine(), goodsale.getGoodprice(), offlinegood.getGoodnumber(), 
					onegoodtotal.doubleValue(), onegoodtotal.doubleValue(), 0, 0, false));
		}
		
		// 保存商品总额、订单总额和支付总额
		mainorder.setGoodtotal(goodtotal.doubleValue());
		BigDecimal ordertotal = goodtotal;
		mainorder.setOrdertotal(ordertotal.doubleValue());
		BigDecimal paymenttotal = ordertotal;
		mainorder.setPaymenttotal(paymenttotal.doubleValue());
		ordersDao.save(mainorder);
		
		// 新增订单商品
		for (Ordergoods ordergood : ordergoods) {
			ordergood.setOrderid(mainorder.getEntityid());
			orderGoodsDao.save(ordergood);
		}
		
		// 发送确认超时延时消息
		Message msg = new Message(OrderTimeoutConsumer.TOPIC, OrderTimeoutTagsEnum.CONFIRM.getTag(), mainorder.getEntityid().toString().getBytes());
		SystemConfig config = (SystemConfig) cacheManager.getObject(SystemConfig.CACHE_KEY, false);
		msg.setDelayTimeLevel(config.getConfirmtimeoutLevel());
		orderTimeoutProducer.send(msg);
		return mainorder.getEntityid();
	}
	
	/**
	 * 新增线上订单
	 * 
	 * @author CJH 2019年7月2日
	 * @param onlineorder 线上订单
	 * @return 订单主键
	 */
	public Long insertOnlineOrder(OnlineOrder onlineorder) {
		// 校验线上订单参数有效性
		if (onlineorder.getReceivingaddressesid() == null) {
			throw new ValidationException("收货地址标识不能为空");
		}
		if (onlineorder.getMemberid() == null) {
			throw new ValidationException("会员标识不能为空");
		}
		if (onlineorder.getDeliverymode() == null) {
			throw new ValidationException("配送方式不能为空");
		}
		if (OrderDeliveryMode.MARKET_DELIVERY.equals(onlineorder.getDeliverymode())) {
			if (onlineorder.getDeliverytime() == null) {
				throw new ValidationException("配送时间不能为空");
			}
			if (OrderDeliveryTime.CUSTOMIZED.equals(onlineorder.getDeliverytime())) {
				if (onlineorder.getDeliverystarttime() == null || onlineorder.getDeliveryendtime() == null) {
					throw new ValidationException("配送起止时间不能为空");
				}
			}
		}
		if (onlineorder.getPaymentmode() == null) {
			throw new ValidationException("支付方式不能为空");
		}
		onlineorder.setIntegralpay(onlineorder.getIntegralpay() != null ? onlineorder.getIntegralpay() : 0);
		if (onlineorder.getIntegralpay() < 0) {
			throw new ValidationException("积分不能小于0");
		}
		onlineorder.setDiamondpay(onlineorder.getDiamondpay() != null ? onlineorder.getDiamondpay() : 0);
		if (onlineorder.getDiamondpay() < 0) {
			throw new ValidationException("钻石不能小于0");
		}
		if (onlineorder.getBuynow() == null) {
			onlineorder.setBuynow(false);
		}
		
		// 校验订单商户商品参数有效性
		if (onlineorder.getOrdermerchants() == null || onlineorder.getOrdermerchants().isEmpty()) {
			throw new ValidationException("订单商户信息不能为空");
		}
		Map<Long, OrderMerchant> ordermerchantsmap = new HashMap<>();
		Map<Long, OnlineGood> onlinegoodmap = new HashMap<>();
		List<Long> submitsaleids = new ArrayList<>();
		for (OrderMerchant ordermerchant : onlineorder.getOrdermerchants()) {
			if (ordermerchant.getMerchantid() == null) {
				throw new ValidationException("商户标识不能为空");
			}
			List<OnlineGood> onlinegoods = ordermerchant.getOnlinegoods();
			if (onlinegoods == null || onlinegoods.isEmpty()) {
				throw new ValidationException("订单商品不能为空");
			}
			for (OnlineGood onlinegood : onlinegoods) {
				if (onlinegood.getSaleid() == null) {
					throw new ValidationException("销售标识不能为空");
				}
				onlinegood.setGoodprice(onlinegood.getGoodprice() != null ? onlinegood.getGoodprice() : 0d);
				if (onlinegood.getGoodprice() <= 0) {
					throw new ValidationException("商品价格不能小于等于0");
				}
				onlinegood.setGoodnumber(onlinegood.getGoodnumber() != null ? onlinegood.getGoodnumber() : 0d);
				if (onlinegood.getGoodnumber() <= 0) {
					throw new ValidationException("商品数量不能小于等于0");
				}
				onlinegoodmap.put(onlinegood.getSaleid(), onlinegood);
				submitsaleids.add(onlinegood.getSaleid());
			}
			ordermerchant.setDeliverycost(ordermerchant.getDeliverycost() != null ? ordermerchant.getDeliverycost() : 0d);
			if (ordermerchant.getDeliverycost() < 0) {
				throw new ValidationException("配送费用不能小于0");
			}
			ordermerchantsmap.put(ordermerchant.getMerchantid(), ordermerchant);
		}
		List<Shoppingcarts> shoppingcarts = shoppingCartsDao.findByMemberidAndSelectstateAndBuynow(onlineorder.getMemberid(), true, onlineorder.getBuynow());
		if (shoppingcarts == null || shoppingcarts.isEmpty()) {
			throw new ValidationException("购物车不能为空");
		}
		List<Long> shoppingcartsaleids = new ArrayList<>();
		for (Shoppingcarts shoppingcart : shoppingcarts) {
			shoppingcartsaleids.add(shoppingcart.getSaleid());
		}
		if (submitsaleids.size() != shoppingcartsaleids.size()) {
			throw new ValidationException("购物车商品不一致");
		}
		submitsaleids.sort(Comparator.naturalOrder());
		shoppingcartsaleids.sort(Comparator.naturalOrder());
		for (int i = 0; i < submitsaleids.size(); i++) {
			if (!submitsaleids.get(i).equals(shoppingcartsaleids.get(i))) {
				throw new ValidationException("购物车商品不一致");
			}
		}
		Receivingaddresses receivingaddresses = receivingAddressesDao.getOne(onlineorder.getReceivingaddressesid());
		if (!receivingaddresses.getMemberid().equals(onlineorder.getMemberid())) {
			throw new ValidationException("收货信息不一致");
		}
		
		// 新增订单
		Orders mainorder = new Orders();
		mainorder.setEntitystate(EntityState.CONFIRMED.getValue());
		mainorder.setMemberid(onlineorder.getMemberid());
		mainorder.setOrderorigin(OrderOrigin.ONLINE.getValue());
		mainorder.setOrdertype(OrderType.NORMAL.getValue());
		mainorder.setReceiver(receivingaddresses.getReceiver());
		mainorder.setProvince(receivingaddresses.getProvince());
		mainorder.setCity(receivingaddresses.getCity());
		mainorder.setCounty(receivingaddresses.getCounty());
		mainorder.setStreet(receivingaddresses.getStreet());
		mainorder.setDetailaddress(receivingaddresses.getDetailaddress());
		mainorder.setMobilephone(receivingaddresses.getMobilephone());
		mainorder.setDeliverystate(OrderDeliveryState.UNSHIPPED.getValue());
		mainorder.setDeliverymode(onlineorder.getDeliverymode().getValue());
		mainorder.setDeliverytime(onlineorder.getDeliverytime() != null ? onlineorder.getDeliverytime().getValue() : null);
		mainorder.setDeliverystarttime(onlineorder.getDeliverystarttime());
		mainorder.setDeliveryendtime(onlineorder.getDeliveryendtime());
		//TODO 配送费用0
		mainorder.setDeliverycost(0d);
		mainorder.setPaymentstate(OrderPaymentState.UNPAID.getValue());
		mainorder.setPaymentmode(onlineorder.getPaymentmode().getValue());
		mainorder.setIntegralpay(onlineorder.getIntegralpay());
		mainorder.setDiamondpay(onlineorder.getDiamondpay());
		Date nowdate = new Date();
		mainorder.setOrdertime(nowdate);
		mainorder.setConfirmtime(nowdate);
		ordersDao.save(mainorder);
		
		// 计算商品总额
		BigDecimal goodtotal = new BigDecimal(0);
		List<Ordergoods> ordergoods = new ArrayList<>();
		boolean issplit = merchantSettlesDao.findByGoodsalesid(shoppingcartsaleids) > 1;
		Iterator<Shoppingcarts> shoppingcartsIterator = shoppingcarts.iterator();
		while (shoppingcartsIterator.hasNext()) {
			// 校验商品有效性
			Shoppingcarts shoppingcart = shoppingcartsIterator.next();
			Goodsales goodsale = goodSalesDao.getOne(shoppingcart.getSaleid());
			if (!EntityState.PUBLISHED.equalsValue(goodsale.getEntitystate())) {
				throw new MessageInfoException("商品已下架");
			}
			OnlineGood onlinegood = onlinegoodmap.get(goodsale.getEntityid());
			BigDecimal submitgoodprice = new BigDecimal(onlinegood.getGoodprice().toString());
			BigDecimal goodprice = new BigDecimal(goodsale.getGoodprice().toString());
			if (submitgoodprice.compareTo(goodprice) != 0) {
				throw new MessageInfoException("商品价格已修改");
			}
			BigDecimal submitgoodnumber = new BigDecimal(onlinegood.getGoodnumber().toString());
			BigDecimal goodnumber = new BigDecimal(shoppingcart.getGoodnumber().toString());
			if (submitgoodnumber.compareTo(goodnumber) != 0) {
				throw new MessageWarnException("商品数量已修改");
			}
			BigDecimal goodstock = new BigDecimal(goodsale.getGoodstock().toString());
			if (goodstock.compareTo(goodnumber) == -1) {
				throw new MessageInfoException("商品库存不足");
			}
			
			// 更新商品剩余库存、按需拆分订单商品
			goodsale.setGoodstock(goodstock.subtract(goodnumber).doubleValue());
			BigDecimal onegoodtotal = goodprice.multiply(goodnumber);
			goodtotal = goodtotal.add(onegoodtotal);
			GoodsInfo goodsinfo = ordersDao.findGoodsinfoBySaleid(shoppingcart.getSaleid());
			Long presplitid = null;
			if (issplit) {
				Orderpresplits orderpresplit = orderPresplitsDao.findByOrderidAndMerchantidAndMarketid(mainorder.getEntityid(), goodsinfo.getMerchantid(), goodsinfo.getMarketid());
				if (orderpresplit == null || orderpresplit.getEntityid() == null) {
					OrderMerchant ordermerchant = ordermerchantsmap.get(goodsinfo.getMerchantid());
					orderpresplit = new Orderpresplits(EntityState.VALID.getValue(), mainorder.getEntityid(), goodsinfo.getMerchantid(), goodsinfo.getMarketid(), ordermerchant.getOrderremark());
					orderPresplitsDao.save(orderpresplit);
				}
				presplitid = orderpresplit.getEntityid();
			} else if (mainorder.getMerchantid() == null || mainorder.getMarketid() == null) {
				mainorder.setMerchantid(goodsinfo.getMerchantid());
				mainorder.setMarketid(goodsinfo.getMarketid());
			}
			
			// 新增订单商品
			Ordergoods ordergood = new Ordergoods(EntityState.VALID.getValue(), mainorder.getEntityid(), shoppingcart.getSaleid(), presplitid, goodsinfo.getGoodname(), 
					goodsinfo.getGoodorigin(), goodsinfo.getGoodpicture(), goodsinfo.getGoodspec(), goodsale.getGoodprice(), shoppingcart.getGoodnumber(), 
					onegoodtotal.doubleValue(), onegoodtotal.doubleValue(), 0, 0, true);
			orderGoodsDao.save(ordergood);
			ordergoods.add(ordergood);
		}
		// 删除选中状态购物车
		shoppingCartsDao.deleteByMemberidAndSelectstateAndBuynow(onlineorder.getMemberid(), true, onlineorder.getBuynow());
		
		// 计算并保存商品总额、订单总额和支付总额
		mainorder.setGoodtotal(goodtotal.doubleValue());
		BigDecimal ordertotal = goodtotal;
		mainorder.setOrdertotal(ordertotal.doubleValue());
		mainorder.setPaymenttotal(ordertotal.doubleValue());
		
		// 计算钻石抵扣优惠
		if (onlineorder.getDiamondpay() > 0) {
			PreferentialResult<Integer> ordergooddiamond = calculateDiamondPreferential(mainorder.getMemberid(), mainorder.getEntityid(), mainorder.getGoodtotal(), false);
			if (ordergooddiamond.getAvailable() != onlineorder.getDiamondpay()) {
				throw new MessageWarnException("钻石优惠信息不一致");
			}
			for (Ordergoods ordergood : ordergoods) {
				Integer diamondpay = ordergooddiamond.getSubitems().get(ordergood.getEntityid());
				if (diamondpay == null) {
					continue;
				}
				ordergood.setDiamondpay(diamondpay);
				BigDecimal ordergoodpaymenttotal = new BigDecimal(ordergood.getPaymenttotal().toString());
				ordergoodpaymenttotal = ordergoodpaymenttotal.subtract(new BigDecimal(diamondpay));
				ordergood.setPaymenttotal(ordergoodpaymenttotal.doubleValue());
			}
			diamondRecordsService.updateLockDiamondByMemberid(mainorder.getMemberid(), onlineorder.getDiamondpay());
			mainorder.setPaymenttotal(ordertotal.subtract(new BigDecimal(onlineorder.getDiamondpay())).doubleValue());
		}
		
		// 发送支付超时延时消息
		Message msg = new Message(OrderTimeoutConsumer.TOPIC, OrderTimeoutTagsEnum.CONFIRMED.getTag(), mainorder.getEntityid().toString().getBytes());
		SystemConfig config = (SystemConfig) cacheManager.getObject(SystemConfig.CACHE_KEY, false);
		msg.setDelayTimeLevel(config.getPaytimeoutLevel());
		orderTimeoutProducer.send(msg);
		return mainorder.getEntityid();
	}
	
	/**
	 * 确认线下订单
	 * 
	 * @author CJH 2019年6月13日
	 * @param orderid 订单标识
	 * @param integralpay 积分支付
	 * @param diamondpay 钻石支付
	 * @param memberid 会员标识
	 */
	public void updateConfirmedOfflineOrder(Long orderid, Integer integralpay, Integer diamondpay, Long memberid) {
		// 校验参数有效性
		if (orderid == null) {
			throw new ValidationException("订单标识不能为空");
		}
		if ((integralpay = integralpay != null ? integralpay : 0) < 0) {
			throw new ValidationException("积分不能小于0");
		}
		if ((diamondpay = diamondpay != null ? diamondpay : 0) < 0) {
			throw new ValidationException("积分不能小于0");
		}
		if (memberid == null) {
			throw new ValidationException("会员标识不能为空");
		}
		
		// 验证订单状态有效性
		Orders order = ordersDao.getOne(orderid);
		if (!EntityState.TBD.equalsValue(order.getEntitystate())) {
			throw new MessageWarnException("订单状态异常");
		}
		
		// 验证抵扣钻石有效性，并拆分钻石到订单商品、更新支付总额
		order.setDiamondpay(diamondpay);
		if (diamondpay > 0) {
			BigDecimal ordertotal = new BigDecimal(order.getOrdertotal().toString());
			BigDecimal diamondpayb = new BigDecimal(diamondpay);
			if (diamondpayb.compareTo(ordertotal) >= 0) {
				throw new MessageWarnException("抵扣钻石不能大于等于订单总额");
			}
			PreferentialResult<Integer> ordergooddiamond = calculateDiamondPreferential(memberid, orderid, order.getGoodtotal(), false);
			if (ordergooddiamond.getAvailable() == diamondpay) {
				throw new MessageInfoException("钻石优惠信息不一致");
			}
			diamondRecordsService.updateLockDiamondByMemberid(memberid, diamondpay);
			order.setPaymenttotal(ordertotal.subtract(diamondpayb).doubleValue());
			List<Ordergoods> ordergoods = orderGoodsDao.findByOrderid(orderid);
			for (Ordergoods ordergood : ordergoods) {
				if (ordergooddiamond.getSubitems().get(ordergood.getEntityid()) == null) {
					continue;
				}
				ordergood.setDiamondpay(ordergooddiamond.getSubitems().get(ordergood.getEntityid()));
			}
		}
		
		// 验证抵扣积分有效性，并锁定积分
		order.setIntegralpay(integralpay);
		if (integralpay > 0) {
			integralRecordsService.updateLockIntegralByMemberid(memberid, integralpay);
		}
		
		// 保存订单确认信息
		order.setEntitystate(EntityState.CONFIRMED.getValue());
		order.setMemberid(memberid);
		order.setConfirmtime(new Date());
		
		// 发送支付超时延时消息
		Message msg = new Message(OrderTimeoutConsumer.TOPIC, OrderTimeoutTagsEnum.CONFIRMED.getTag(), order.getEntityid().toString().getBytes());
		SystemConfig config = (SystemConfig) cacheManager.getObject(SystemConfig.CACHE_KEY, false);
		msg.setDelayTimeLevel(config.getPaytimeoutLevel());
		orderTimeoutProducer.send(msg);
	}
	
	/**
	 * 订单完成付款
	 * 
	 * @author CJH 2019年6月13日
	 * @param pir 支付接口响应对象
	 */
	public void updateCompletePayment(PaymentInterfaceResponse pir) {
		// 校验参数有效性
		if (pir.getOrderid() == null) {
			throw new ValidationException("订单标识不能为空");
		}
		if (StringUtils.isBlank(pir.getTradeno())) {
			throw new ValidationException("交易号不能为空");
		}
		
		// 校验订单状态有效性
		Orders mainorder = ordersDao.getOne(pir.getOrderid());
		if (EntityState.CANC.equalsValue(mainorder.getEntitystate())) {
			throw new MessageInfoException("订单支付超时");
		}
		if (!EntityState.CONFIRMED.equalsValue(mainorder.getEntitystate()) || !OrderPaymentState.UNPAID.equalsValue(mainorder.getPaymentstate())) {
			throw new MessageInfoException("订单状态异常");
		}
		
		// 校验订单商品有效性
		if (orderGoodsDao.existsInvalidByOrderid(mainorder.getEntityid())) {
			throw new MessageInfoException("商品已下架");
		}
		
		// 使用抵扣钻石和积分
		if (mainorder.getDiamondpay() > 0) {
			diamondRecordsService.updateUseDiamondByOrderid(mainorder.getEntityid(), mainorder.getDiamondpay());
		}
		if (mainorder.getIntegralpay() > 0) {
			integralRecordsService.updateUseIntegralByOrderid(mainorder.getEntityid(), mainorder.getIntegralpay());
		}
		
		// 保存订单付款信息
		Date nowdate = new Date();
		mainorder.setPaymentstate(OrderPaymentState.PAID.getValue());
		mainorder.setPaymenttradeno(pir.getTradeno());
		mainorder.setPaytime(nowdate);
		if (OrderOrigin.OFFLINE.equalsValue(mainorder.getOrderorigin())) {
			// 线下订单保存订单完成信息，并增加商户资金
			mainorder.setDeliverystate(OrderDeliveryState.RECEIVED.getValue());
			mainorder.setSendtime(nowdate);
			mainorder.setReceivetime(nowdate);
			mainorder.setCompletetime(nowdate);
			mainorder.setEntitystate(EntityState.OTS.getValue());
			mainorder.setRefundendtime(nowdate);
			integralRecordsService.updateOrderIncomeIntegralByOrderid(mainorder.getEntityid());
			capitalRecordsService.updateOrderRevenueCapitalByMerchantid(mainorder.getEntityid());
		} else if (OrderOrigin.ONLINE.equalsValue(mainorder.getOrderorigin())) {
			if (orderPresplitsDao.existsByOrderid(mainorder.getEntityid())) {
				// 按商户和市场拆分订单
				mainorder.setEntitystate(EntityState.HBS.getValue());
				mainorder.setSplittime(nowdate);
				String splitreason = "订单商品不同商户或者不同市场拆分";
				mainorder.setSplitreason(splitreason);
				List<Ordergoods> ordergoods = orderGoodsDao.findByOrderid(mainorder.getEntityid());
				for (Ordergoods ordergood : ordergoods) {
					Orderpresplits orderpresplit = orderPresplitsDao.getOne(ordergood.getPresplitid());
					Orders childorder = ordersDao.findByOriginalorderAndMerchantidAndMarketid(mainorder.getEntityid(), orderpresplit.getMerchantid(), orderpresplit.getMarketid());
					if (childorder == null || childorder.getEntityid() == null) {
						// 新增子订单
						childorder = new Orders();
						childorder.setEntitystate(EntityState.CONFIRMED.getValue());
						childorder.setMemberid(mainorder.getMemberid());
						childorder.setMerchantid(orderpresplit.getMerchantid());
						childorder.setMarketid(orderpresplit.getMarketid());
						childorder.setOrderorigin(mainorder.getOrderorigin());
						childorder.setOrdertype(mainorder.getOrdertype());
						childorder.setOriginalorder(mainorder.getEntityid());
						childorder.setReceiver(mainorder.getReceiver());
						childorder.setProvince(mainorder.getProvince());
						childorder.setCity(mainorder.getCity());
						childorder.setCounty(mainorder.getCounty());
						childorder.setStreet(mainorder.getStreet());
						childorder.setDetailaddress(mainorder.getDetailaddress());
						childorder.setMobilephone(mainorder.getMobilephone());
						childorder.setOrderremark(orderpresplit.getOrderremark());
						childorder.setOrdertotal(ordergood.getGoodtotal());
						childorder.setGoodtotal(ordergood.getGoodtotal());
						childorder.setDeliverystate(mainorder.getDeliverystate());
						childorder.setDeliverymode(mainorder.getDeliverymode());
						childorder.setDeliverytime(mainorder.getDeliverytime());
						childorder.setDeliverystarttime(mainorder.getDeliverystarttime());
						childorder.setDeliveryendtime(mainorder.getDeliveryendtime());
						childorder.setDeliverycost(0d);
						childorder.setPaymentstate(mainorder.getPaymentstate());
						childorder.setPaymentmode(mainorder.getPaymentmode());
						BigDecimal paymenttotal = new BigDecimal(childorder.getOrdertotal().toString());
						if (ordergood.getDiamondpay() > 0) {
							paymenttotal = paymenttotal.subtract(new BigDecimal(ordergood.getDiamondpay()));
						}
						childorder.setPaymenttotal(paymenttotal.doubleValue());
						childorder.setPaymenttradeno(mainorder.getPaymenttradeno());
						childorder.setTradecreatetime(mainorder.getTradecreatetime());
						childorder.setTradecompletetime(mainorder.getTradecompletetime());
						childorder.setIntegralpay(ordergood.getIntegralpay());
						childorder.setDiamondpay(ordergood.getDiamondpay());
						childorder.setOrdertime(mainorder.getOrdertime());
						childorder.setConfirmtime(mainorder.getConfirmtime());
						childorder.setPaytime(mainorder.getPaytime());
						childorder.setSplittime(mainorder.getSplittime());
						childorder.setSplitreason(mainorder.getSplitreason());
						childorder.setPartialrefund(mainorder.getPartialrefund());
						ordersDao.save(childorder);
					} else {
						// 计算订单总额、商品总额、支付总额和钻石支付
						BigDecimal ordertotal = new BigDecimal(childorder.getOrdertotal().toString());
						BigDecimal goodtotal = new BigDecimal(childorder.getGoodtotal().toString());
						BigDecimal childgoodtotal = new BigDecimal(ordergood.getGoodtotal().toString());
						BigDecimal paymenttotal = new BigDecimal(childorder.getPaymenttotal().toString());
						BigDecimal diamondpay = new BigDecimal(childorder.getDiamondpay());
						BigDecimal childdiamondpay = new BigDecimal(ordergood.getDiamondpay());
						ordertotal = ordertotal.add(childgoodtotal);
						childorder.setOrdertotal(ordertotal.doubleValue());
						goodtotal = goodtotal.add(childgoodtotal);
						childorder.setGoodtotal(goodtotal.doubleValue());
						paymenttotal = paymenttotal.add(childgoodtotal);
						if (ordergood.getDiamondpay() > 0) {
							paymenttotal = paymenttotal.subtract(childdiamondpay);
						}
						childorder.setPaymenttotal(paymenttotal.doubleValue());
						diamondpay = diamondpay.add(childdiamondpay);
						childorder.setDiamondpay(diamondpay.intValue());
					}
					ordergood.setOrderid(childorder.getEntityid());
				}
			} else {
				// 线上无需拆分的订单
			}
		}
	}
	
	/**
	 * 取消待确认订单
	 * 
	 * @author CJH 2019年7月24日
	 * @param orderid 订单标识
	 * @param ordercanceltype 取消类型
	 * @param cancelreason 取消原因
	 */
	public void updateCancelConfirmOrder(Long orderid, OrderCancelType ordercanceltype, String cancelreason) {
		// 校验参数有效性
		if (orderid == null) {
			throw new ValidationException("订单标识不能为空");
		}
		if (ordercanceltype == null) {
			throw new ValidationException("取消类型不能为空");
		}
		
		// 校验订单状态有效性
		Orders order = ordersDao.getOne(orderid);
		if (!EntityState.TBD.equalsValue(order.getEntitystate())) {
			throw new MessageInfoException("订单状态异常");
		}
		
		// 保存订单取消信息
		order.setCanceltype(ordercanceltype.getValue());
		order.setCanceltime(new Date());
		order.setCancelreason(StringUtils.isNotBlank(cancelreason) ? cancelreason : ordercanceltype.getText());
		order.setEntitystate(EntityState.CANC.getValue());
	}
	
	/**
	 * 取消已确认订单
	 * 
	 * @author CJH 2019年6月24日
	 * @param orderid 订单标识
	 * @param ordercanceltype 取消类型
	 * @param cancelreason 取消原因
	 */
	public void updateCancelConfirmedOrder(Long orderid, OrderCancelType ordercanceltype, String cancelreason) {
		// 校验参数有效性
		if (orderid == null) {
			throw new ValidationException("订单标识不能为空");
		}
		if (ordercanceltype == null) {
			throw new ValidationException("取消类型不能为空");
		}
		
		// 校验订单状态有效性
		Orders order = ordersDao.getOne(orderid);
		if (!EntityState.CONFIRMED.equalsValue(order.getEntitystate()) || !OrderPaymentState.UNPAID.equalsValue(order.getPaymentstate())) {
			throw new MessageInfoException("订单已支付无法取消");
		}
		
		// 确定订单后锁定的钻石和积分解除锁定
		if (order.getDiamondpay() > 0) {
			diamondRecordsService.updateUnlockDiamondByMemberid(order.getMemberid(), order.getDiamondpay());
		}
		if (order.getIntegralpay() > 0) {
			integralRecordsService.updateUnlockIntegralByMemberid(order.getMemberid(), order.getIntegralpay());
		}
		
		// 线上订单恢复商品库存
		if (OrderOrigin.ONLINE.equalsValue(order.getOrderorigin())) {
			List<Ordergoods> ordergoods = orderGoodsDao.findByOrderid(orderid);
			for (Ordergoods ordergood : ordergoods) {
				Goodsales goodsale = goodSalesDao.getOne(ordergood.getSaleid());
				if (!EntityState.PUBLISHED.equalsValue(goodsale.getEntitystate())) {
					// 已下架
					continue;
				}
				BigDecimal goodstock = new BigDecimal(goodsale.getGoodstock());
				BigDecimal goodnumber = new BigDecimal(ordergood.getGoodnumber());
				goodsale.setGoodstock(goodstock.add(goodnumber).doubleValue());
			}
		}
		
		// 保存订单取消信息
		order.setCanceltype(ordercanceltype.getValue());
		order.setCanceltime(new Date());
		order.setCancelreason(StringUtils.isNotBlank(cancelreason) ? cancelreason : ordercanceltype.getText());
		order.setEntitystate(EntityState.CANC.getValue());
	}
	
	/**
	 * 完成订单
	 * 
	 * @author CJH 2019年7月31日
	 * @param orderid 订单标识
	 */
	public void updateCompleteOrder(Long orderid) {
		// 校验参数有效性
		if (orderid == null) {
			throw new ValidationException("订单标识不能为空");
		}
		
		Orders order = ordersDao.getOne(orderid);
		if (!EntityState.CONFIRMED.equalsValue(order.getEntitystate())) {
			throw new MessageInfoException("订单状态异常");
		}
		// 保存订单完成信息
		order.setEntitystate(EntityState.OTS.getValue());
		order.setDeliverystate(OrderDeliveryState.RECEIVED.getValue());
		Date nowdate = new Date();
		order.setReceivetime(nowdate);
		order.setCompletetime(nowdate);
		// 计算退款截止时间
		SystemConfig config = (SystemConfig) cacheManager.getObject(SystemConfig.CACHE_KEY, false);
		if (config.getRefundtimeout() != null) {
			Calendar refunddate = Calendar.getInstance();
			refunddate.add(Calendar.DATE, config.getRefundtimeout());
			order.setRefundendtime(refunddate.getTime());
		}
		
		integralRecordsService.updateOrderIncomeIntegralByOrderid(orderid);
		capitalRecordsService.updateOrderRevenueCapitalByMerchantid(orderid);
		
		if (order.getOriginalorder() != null && !ordersDao.existsByOriginalorderAndEntitystate(order.getOriginalorder(), EntityState.CONFIRMED.getValue())) {
			// 当拆分子订单全部完成时，保存主订单完成信息
			Orders mainorder = ordersDao.getOne(order.getOriginalorder());
			mainorder.setDeliverystate(OrderDeliveryState.RECEIVED.getValue());
			mainorder.setReceivetime(nowdate);
			mainorder.setCompletetime(nowdate);
		}
	}
	
	/**
	 * 系统申请订单退款
	 * 
	 * @author CJH 2019年8月8日
	 * @param ordersid 订单标识
	 * @param applydesc 申请描述
	 */
	public void updateApplyOrdersRefund(Long ordersid, String applydesc) {
		if (ordersid == null) {
			throw new ValidationException("订单标识不能为空");
		}
		if (refundRecordsDao.existsValidByOrderid(ordersid)) {
			throw new MessageInfoException("订单状态无法申请退款");
		}
		Refundrecords refundrecord = new Refundrecords();
		refundrecord.setEntitystate(EntityState.OBLIGATION.getValue());
		refundrecord.setOrderid(ordersid);
		refundrecord.setApplytype(OrderRefundApplyType.SYSTEM.getValue());
		refundrecord.setApplytime(new Date());
		refundrecord.setApplydesc(applydesc);
		refundrecord.setPartialrefund(false);
		refundRecordsDao.save(refundrecord);
		
		List<Ordergoods> ordergoods = orderGoodsDao.findByOrderid(ordersid);
		BigDecimal refundtotal = new BigDecimal(0);
		Integer integralrefund = 0;
		Integer diamondrefund = 0;
		for (Ordergoods ordergood : ordergoods) {
			refundtotal = refundtotal.add(new BigDecimal(ordergood.getPaymenttotal().toString()));
			integralrefund += ordergood.getIntegralpay();
			diamondrefund += ordergood.getDiamondpay();
			refundGoodsDao.save(new Refundgoods(EntityState.VALID.getValue(), refundrecord.getEntityid(), ordergood.getEntityid()));
		}
		refundrecord.setRefundtotal(refundtotal.doubleValue());
		refundrecord.setIntegralrefund(integralrefund);
		refundrecord.setDiamondrefund(diamondrefund);
		
		updateHandleRefund(refundrecord.getEntityid(), true, null);
	}
	
	/**
	 * 申请订单商品退款
	 * 
	 * @author CJH 2019年8月8日
	 * @param ordersgoodsids 订单商品标识
	 * @param applytype 申请类型
	 * @param applydesc 申请描述
	 */
	public void updateApplyOrdersGoodsRefund(List<Long> ordersgoodsids, OrderRefundApplyType applytype, String applydesc) {
		if (ordersgoodsids == null || ordersgoodsids.isEmpty()) {
			throw new ValidationException("订单商品标识不能为空");
		}
		if (applytype == null) {
			throw new ValidationException("申请类型不能为空");
		}
		List<Ordergoods> ordergoodslist = orderGoodsDao.findAllById(ordersgoodsids);
		if (ordergoodslist == null || ordersgoodsids.size() != ordergoodslist.size()) {
			throw new MessageWarnException("申请退款订单商品无效");
		}
		Long ordersid = null;
		for (Ordergoods ordergoods : ordergoodslist) {
			if (!ordergoods.getSupportrefund()) {
				throw new MessageWarnException("订单商品不支持退款");
			}
			if (ordersid == null) {
				ordersid = ordergoods.getOrderid();
				Orders orders = ordersDao.getOne(ordersid);
				if (orders.getRefundendtime().compareTo(new Date()) < 0) {
					throw new MessageWarnException("订单申请退款已超时");
				}
				continue;
			}
			if (ordersid.longValue() != ordergoods.getOrderid().longValue()) {
				throw new MessageWarnException("申请退款订单商品不属于同一个订单");
			}
		}
		boolean partialrefund = ordergoodslist.size() != orderGoodsDao.countByOrderid(ordersid);
		if (refundRecordsDao.existsValidByOrderid(ordersid)) {
			throw new MessageInfoException("订单已申请退款");
		}
		Refundrecords refundrecord = new Refundrecords();
		refundrecord.setEntitystate(EntityState.OBLIGATION.getValue());
		refundrecord.setOrderid(ordersid);
		refundrecord.setApplytype(OrderRefundApplyType.SYSTEM.getValue());
		refundrecord.setApplytime(new Date());
		refundrecord.setApplydesc(applydesc);
		refundrecord.setPartialrefund(partialrefund);
		refundRecordsDao.save(refundrecord);
		
		BigDecimal refundtotal = new BigDecimal(0);
		Integer integralrefund = 0;
		Integer diamondrefund = 0;
		for (Ordergoods ordergoods : ordergoodslist) {
			refundtotal = refundtotal.add(new BigDecimal(ordergoods.getPaymenttotal().toString()));
			integralrefund += ordergoods.getIntegralpay();
			diamondrefund += ordergoods.getDiamondpay();
			refundGoodsDao.save(new Refundgoods(EntityState.VALID.getValue(), refundrecord.getEntityid(), ordergoods.getEntityid()));
		}
		refundrecord.setRefundtotal(refundtotal.doubleValue());
		refundrecord.setIntegralrefund(integralrefund);
		refundrecord.setDiamondrefund(diamondrefund);
	}
	
	/**
	 * 处理退款申请
	 * 
	 * @author CJH 2019年8月8日
	 * @param recordid 退款记录标识
	 * @param isagree 同意退款
	 * @param handledesc 处理描述
	 */
	public void updateHandleRefund(Long recordid, boolean isagree, String handledesc) {
		if (recordid == null) {
			throw new ValidationException("退款记录标识不能为空");
		}
		Refundrecords refundrecord = refundRecordsDao.getOne(recordid);
		refundrecord.setHandletime(new Date());
		refundrecord.setHandledesc(handledesc);
		if (isagree) {
			refundrecord.setEntitystate(EntityState.REFUNDING.getValue());
			
			try {
				AbstractInterfaceService.applyRefund(refundrecord.getOrderid());
			} catch (Exception e) {
				throw new MessageWarnException("未找到订单");
			}
		} else {
			refundrecord.setEntitystate(EntityState.UNDO.getValue());
		}
	}
	
	/**
	 * 完成退款
	 * 
	 * @author CJH 2019年8月8日
	 * @param pir 支付接口响应对象
	 */
	public void updateCompleteRefund(PaymentInterfaceResponse pir) {
		if (pir.getOrderid() == null) {
			throw new ValidationException("订单标识不能为空");
		}
		Refundrecords refundrecord = refundRecordsDao.findRefundingByOrderid(pir.getOrderid());
		if (refundrecord == null) {
			throw new MessageInfoException("未找到订单待退款记录");
		}
		
		refundrecord.setEntitystate(EntityState.REFUNDED.getValue());
		refundrecord.setTradeno(pir.getTradeno());
		refundrecord.setRefundtime(pir.getTradetime());
		
		Orders orders = ordersDao.getOne(pir.getOrderid());
		if (!refundrecord.getPartialrefund()) {
			orders.setEntitystate(EntityState.CANC.getValue());
		}
		orders.setDeliverystate(OrderDeliveryState.REFUNDED.getValue());
		orders.setPaymentstate(OrderPaymentState.REFUNDED.getValue());
		orders.setRefundtradeno(pir.getTradeno());
		orders.setRefundtime(pir.getTradetime());
		orders.setPartialrefund(refundrecord.getPartialrefund());
		orders.setRefundtotal(refundrecord.getRefundtotal());
		orders.setIntegralrefund(refundrecord.getIntegralrefund());
		orders.setDiamondrefund(refundrecord.getDiamondrefund());
		
		List<Ordergoods> goods = orderGoodsDao.getRefundGoods(refundrecord.getEntityid());
		for (Ordergoods good : goods) {
			good.setEntitystate(EntityState.REFUNDED.getValue());
		}
		
		if (orders.getIntegralrefund() > 0) {
			integralRecordsService.updateRefundIntegralByOrderid(pir.getOrderid(), orders.getIntegralrefund());
		}
		if (orders.getDiamondrefund() > 0) {
			diamondRecordsService.updateRefundDiamondByOrderid(pir.getOrderid(), orders.getDiamondrefund());
		}
		
		aliyunInterfaceService.sendAccountRemind(NotifyType.REFUND_REMIND, orders.getMerchantid(), refundrecord.getRefundtotal());
	}
	
	/**
	 * 查询订单。
	 * @author Chrise 2019年6月19日
	 * @param api 支付接口。
	 * @param order 订单标识。
	 * @param member 会员标识。
	 * @return 订单对象，订单无效返回false，查询出错返回true。
	 */
	public Object queryOrderForConfirm(String api, String order, long member) {
		try {
			long orderid = Long.valueOf(order);
			
			// 获取、验证支付订单
			PayOrder po = this.ordersDao.queryPayOrder(orderid);
			if (!this.verifyPayOrder(po)) {
				LOGGER.error("The order [{}] is invalid with order object [{}].", order, po);
				return false;
			}
			
			// 设置支付订单属性
			po.setPaymentapi(api);
			if (EntityState.TBD.equalsValue(po.getOrderstate())) {
				// 核算钻石优惠
				PreferentialResult<Integer> diamond = calculateDiamondPreferential(member, orderid, po.getOrdertotal(), false);
				
				po.setPaymenttotal(po.getOrdertotal());
				po.setDiamondnum(diamond.getAvailable());
				po.setDiamondpay(diamond.getTotal());
				po.setNeedconfirm(true);
			} else {
				// 还原可用钻石
				int diamondnum = this.membersDao.queryAvailableDiamond(member);
				diamondnum += po.getDiamondpay();
				
				po.setDiamondnum(diamondnum);
				po.setNeedconfirm(false);
			}
			
			return po;
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
		
		return true;
	}
	
	/**
	 * 保存支付交易。
	 * @author Chrise 2019年6月20日
	 * @param order 订单标识。
	 * @param mode 支付方式。
	 * @param trade 交易号。
	 * @return 保存成功时返回true，否则返回false。
	 */
	public boolean savePayTrade(long order, OrderPaymentMode mode, String trade) {
		try {
			this.ordersDao.savePayTrade(order, mode, trade);
			return true;
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
		return false;
	}
	
	/**
	 * 核算钻石优惠。
	 * @author Chrise 2019年7月11日
	 * @param member 会员标识。
	 * @param order 订单标识。
	 * @param total 商品总额。
	 * @param buynow 立即购买。
	 * @return 优惠结果。
	 */
	public PreferentialResult<Integer> calculateDiamondPreferential(long member, long order, double total, boolean buynow) {
		// 获取系统配置
		SystemConfig sc = (SystemConfig)this.cacheManager.getObject(SystemConfig.CACHE_KEY, false);
		if (sc == null) {
			LOGGER.error("The system config not found for order [{}].", order);
			throw new RuntimeException("The system config not found.");
		}
		
		// 获取可用钻石并计算最大抵扣钻石数
		int diamondnum = this.membersDao.queryAvailableDiamond(member);
		int diamondmax = ((Double)Math.min(Math.floor(total * sc.getDiadeductratio() / 100.0), diamondnum)).intValue();
		if (diamondmax <= 0) return new PreferentialResult<Integer>(diamondnum, 0);
		
		// 查询订单商品
		List<Ordergoods> ordergoods = null;
		if (order > 0L) ordergoods = this.orderGoodsDao.queryFromOrder(order);	// 订单已生成从订单读数据
		else {
			// 订单未生成从购物车读数据
			ordergoods = this.orderGoodsDao.queryFromShoppingcart(member, buynow);
			
			// 验证商品总金额
			double temp = 0.0;
			for (Ordergoods og : ordergoods) {
				temp += og.getGoodtotal();
			}
			if (temp != total) {
				LOGGER.error("The goods total has changed from [{}] to [{}] for member [{}].", total, temp, member);
				throw new RuntimeException("The goods total has changed.");
			}
		}
		
		// 删除商品金额小于等于1的商品
		ordergoods.removeIf(og -> {
			if (og.getGoodtotal().doubleValue() <= MIN_PAY_AMOUNT) return true;
			return false;
		});
		
		// 计算分项优惠分摊比例
		List<SubitemPreferential<Integer>> subitems = new ArrayList<SubitemPreferential<Integer>>();
		ordergoods.forEach(og -> {
			double ratio = og.getGoodtotal() / total;
			subitems.add(new SubitemPreferential<Integer>(og.getEntityid(), ratio, og.getGoodtotal(), 0));
		});
		
		// 按分摊比例倒序排列
		Collections.sort(subitems, (o1, o2) -> {
			return o2.getRatio().compareTo(o1.getRatio());
		});
		
		int diamondtotal = 0;	// 分摊抵扣钻石总数
		
		// 首轮按比例向下取整分摊
		for (SubitemPreferential<Integer> subitem : subitems) {
			int amount = ((Double)Math.floor(diamondmax * subitem.getRatio())).intValue();
			subitem.setAmount(subitem.getAmount() + amount);
			
			diamondtotal += amount;
		}
		
		// 存在未分摊的钻石
		while (diamondtotal < diamondmax) {
			boolean stopshare = false;
			int diamondremain = diamondmax - diamondtotal;
			
			// 按比例从高到底平均分摊
			for (int index = 0; index < subitems.size(); index ++) {
				SubitemPreferential<Integer> subitem = subitems.get(index);
				
				// 本身无分摊空间时中断本轮分摊
				if (subitem.getTotal() - subitem.getAmount() <= MIN_PAY_AMOUNT) {
					stopshare = (index == 0);	// 最大分摊比例无法分摊时终止分摊
					break;
				}
				
				subitem.setAmount(subitem.getAmount() + 1);	// 平均分摊钻石
				
				diamondtotal ++;	// 分摊抵扣钻石数+1
				diamondremain --;	// 剩余未分摊钻石数-1
				
				// 无剩余未分摊钻石时中断本轮分摊
				if (diamondremain <= 0) {
					stopshare = true;	// 无剩余未分摊钻石时终止分摊
					break;
				}
			}
			
			if (stopshare) break;	// 终止分摊
		}
		
		// 构造优惠结果
		PreferentialResult<Integer> result = new PreferentialResult<Integer>(diamondnum, diamondtotal);
		subitems.forEach(subitem -> {
			if (subitem.getAmount() > 0) result.addSubitemPreferential(subitem.getGood(), subitem.getAmount());
		});
		
		return result;
	}
	
	/**
	 * 验证支付订单。
	 * @author Chrise 2019年6月19日
	 * @param order 支付订单对象。
	 * @return 支付订单有效时返回true，否则返回false。
	 */
	private boolean verifyPayOrder(PayOrder order) {
		// 订单为空
		if (order == null) return false;
		
		// 订单类型无效
		if (!OrderType.NORMAL.equalsValue(order.getOrdertype()) && !OrderType.RECHARGE.equalsValue(order.getOrdertype())) return false;
		
		// 订单总额无效
		if (order.getOrdertotal() <= 0.0) return false;
		
		// 订单状态无效
		if (!EntityState.TBD.equalsValue(order.getOrderstate()) && !EntityState.CONFIRMED.equalsValue(order.getOrderstate())) return false;
		
		// 支付状态无效
		if (!OrderPaymentState.UNPAID.equalsValue(order.getPaymentstate())) return false;
		
		return true;
	}
	
}
